// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.api.ads.tools.jaxws;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 * A wrapper around the properties files from the Java client library which
 * pulls out pertinent information.
 *
 * The properties files that this class is designed to wrap describe Google's
 * Ads APIs. Each API typically has several servers (typically production and a
 * sandbox), several version, and several individual web services. Additionally,
 * the AdWords API has a concept of "groups" that must be described.
 *
 * For examples of what these properties files are expected to look like, check
 * the {@code com.google.api.ads.dfa.lib.conf.props} and
 * {@code com.google.api.ads.adwords.lib.conf.props} packages.
 *
 * @author Joseph DiLallo
 */
public class ApiProperties {

  private String apiName;
  private Properties properties;

  private static final String GROUPS_KEY = "groups";
  private static final String WSDL_POSTFIX_KEY = "wsdl.postfix";
  private static final String SERVICES_KEY = "services";
  private static final String SERVER_KEY = "server.production";
  private static final String VERSIONS_KEY = "versions";
  private static final String PACKAGE_PREFIX_KEY = "package.prefix";
  private static final String HAS_GROUPS_KEY = "hasgroups";
  private static final String PROPERTY_PREFIX = "api";
  private static final String VERSIONED_KEY_MARKER = "version";
  private static final String FRAMEWORK_STRING_TO_REPLACE = "${api.framework}";

  /**
   * Reads in properties from the given path.
   *
   * @param apiName The name of the API whose properties this encapsulates
   * @param propertiesFilePath The fully qualified path to the API's properties
   *        file
   * @throws IOException if the properties file cannot be located or read
   */
  public ApiProperties(String apiName, String propertiesFilePath) throws IOException {
    this.apiName = apiName;
    properties = new Properties();
    FileReader inputFile = new FileReader(new File(propertiesFilePath));
    properties.load(inputFile);
    inputFile.close();
  }

  /**
   * Testable constructor.
   *
   * @param apiName The name of the API whose properties this encapsulates
   * @param properties The properties for this API
   */
  @VisibleForTesting
  ApiProperties(String apiName, Properties properties) {
    this.apiName = apiName;
    this.properties = properties;
  }

  /**
   * Replaces the string {@code "${api.framework}"} in the package prefix with
   * the API framework in use.
   *
   * @param apiFramework The framework to substitute into the package prefix
   */
  public void correctPackagePrefix(String apiFramework) {
    properties.setProperty(Joiner.on(".").join(PROPERTY_PREFIX, apiName, PACKAGE_PREFIX_KEY),
        getPackagePrefix().replace(FRAMEWORK_STRING_TO_REPLACE, apiFramework));
  }

  public String getWsdlPostfix() {
    return getPropertyEndingWith(WSDL_POSTFIX_KEY);
  }

  public String getPackagePrefix() {
    return getPropertyEndingWith(PACKAGE_PREFIX_KEY);
  }

  public String getServerUrl() {
    return getPropertyEndingWith(SERVER_KEY);
  }

  public String[] getVersions() {
    return getPropertyEndingWith(VERSIONS_KEY).split(",");
  }

  public boolean hasGroups(String version) {
    return Boolean.parseBoolean(getVersionedPropertyEndingWith(version, HAS_GROUPS_KEY));
  }

  public String[] getGroups(String version) {
    return getVersionedPropertyEndingWith(version, GROUPS_KEY).split(",");
  }

  public String[] getServices(String version) {
    return getVersionedPropertyEndingWith(version, SERVICES_KEY).split(",");
  }

  public String[] getServices(String version, String group) {
    return getVersionedPropertyEndingWith(version, group + "." + SERVICES_KEY).split(",");
  }

  private String getVersionedPropertyEndingWith(String version, String postfix) {
    return properties.getProperty(
        Joiner.on(".").join(PROPERTY_PREFIX, apiName, VERSIONED_KEY_MARKER, version, postfix));
  }

  private String getPropertyEndingWith(String postfix) {
    return properties.getProperty(Joiner.on(".").join(PROPERTY_PREFIX, apiName, postfix));
  }
}
